home *** CD-ROM | disk | FTP | other *** search
/ Mission 1 / Mission 1 / Mission 1.iso / pd_share / cpx_acc / eyes / eyes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-16  |  23.3 KB  |  773 lines

  1. /* eyes.c
  2.  
  3.    A just-for-fun accessory. It really looks where the mouse is.
  4.    A public domain program by
  5.  
  6.    Peter Kirchgessner
  7.    Laubenheimer Str. 78
  8.    D W6500 Mainz-Weisenau
  9.    Federal Republic of Germany
  10.  
  11.    for Atari ST (monochrome/color).
  12.    Tested with Megamax Laser C V 2.0
  13.                Borland Turbo C V 2.0
  14.  
  15.    Idea by Silicon Graphics.
  16.  
  17.    Created     : 10-Feb-91       V 0.01
  18.    Last change : 31-Mar-91       V 1.00
  19. */
  20. /* Description : This accessory opens automatically a window
  21.      where two eyes are displayed. These eyes are looking in
  22.      direction to the mouse pointer. The positions of the pupils
  23.      are updated every 0.15 sec (only on change). With a single
  24.      click inside the window it will become the top window.
  25.      Then it can be moved by pressing the left mouse button
  26.      when inside the window and hold it down during move.
  27.      With a double click, the window is closed and it will no
  28.      longer automatically open after start or end of a program.
  29.      When activating the accessory via its menu entry, automatic
  30.      open is re-enabled.
  31.      If the window is totally covered, the accessory tries to
  32.      find an area where it can look through. Then the window is
  33.      moved to that location.
  34. */
  35.  
  36. #ifdef __TURBOC__
  37. /* These includes for Turbo C (__TURBOC__ is predefined) */
  38.  
  39. #include <aes.h>
  40. #include <vdi.h>
  41. #include <stdlib.h>
  42.  
  43. #else
  44. /* Otherwise Laser C needs these ones */
  45.  
  46. #include <obdefs.h>
  47. #include <gemdefs.h>
  48.  
  49. int contrl[15],intin[128],ptsin[128],intout[128],ptsout[128];
  50. /* The following is special for Laser C. */
  51. /* We dont need the default 8KB stack.   */
  52. long _stksize = 1400L;
  53.  
  54. #endif
  55.  
  56. #define max(a,b) (((a) > (b)) ? (a) : (b))
  57. #define min(a,b) (((a) < (b)) ? (a) : (b))
  58. #define NOT_VALID 32000
  59. #define TRUE 1
  60. #define FALSE 0
  61.  
  62. /* Size of work area of window */
  63. #define WORK_WIDTH 52
  64. #define WORK_HEIGHT 42
  65.  
  66. /* Define SHOW_ACTIVITY to invert a 2x2 rectangle at position
  67.    (0,0) on each activation of the accessory
  68. */
  69. /*
  70. #define SHOW_ACTIVITY
  71. */
  72.                             /* Pseudo-random number generator */
  73. static int myrand = 1;      /* Startvalue */
  74. #define RAND() (myrand = (myrand * 16017 + 1) & 0x7fff)
  75.  
  76. /* Position of eyes from center of work area */
  77. #define EYE_DX 9
  78. #define EYE_DY 7
  79.  
  80. /* The following variables can be found in the .ACC file  */
  81. /* by searching for the 4 byte hexadecimal magic number.  */
  82. /* This allows some modifications of the program without  */
  83. /* compiling the source (position of window at start,     */
  84. /* window components, automatic open after start)         */
  85.  
  86. static long magic = 0x31415926L;  /* Magic for following data */
  87.  
  88. static int work_x_origin = 85; /* Origin of own windows work area */
  89. static int work_y_origin = 20; /* within Desktop work area */
  90.  
  91.                                /* Components of window: 0 or 11 */
  92. static int win_components = 0; /* or (NAME | CLOSER | MOVER)    */
  93.  
  94. static int auto_open = TRUE;   /* Flag for automatic open of accessory */
  95.  
  96. /* global variables */
  97.  
  98. extern int _app;     /* Application-flag */
  99. static int handle;   /* handle for VDI routines */
  100.  
  101. #define MENU_ENTRY "  Eyes        "
  102.  
  103.                   /*** Variables for window-handling ***/
  104.       /* Handle of open window (<= 0: window not open) */
  105. static int whandle;
  106.  
  107.               /* Handles for GEM and VDI */
  108. static int appl_id,menu_id;
  109.  
  110. static int desk_work[4];   /* Desktop work area as rectangle */
  111. static int desk_size[2];   /* Width and height of desktop work area */
  112.  
  113. static int mouse_x,mouse_y, /* current and last mouse position */
  114.            last_x = NOT_VALID,last_y = NOT_VALID;
  115.  
  116.                     
  117. typedef struct       /* Position of pupils of eyes */
  118.   {
  119.    int left_dx;
  120.    int right_dx;
  121.    int dy;
  122.   } EYE_DATA;
  123.  
  124. static EYE_DATA new_eye,
  125.                 last_eye = {NOT_VALID,NOT_VALID,NOT_VALID};
  126.  
  127. #ifdef __TURBOC__
  128.  
  129. /* Prototypes for Turbo C */
  130. static void position (int mdx,int mdy,int *dx,int *dy);
  131. static int new_position (int mousex,int mousey);
  132. static void save_position (void);
  133. static void eyes (EYE_DATA *eye);
  134. static void face (void);
  135. static void open_window (int use_grow_box);
  136. static void open_back_window (int use_grow_box);
  137. static void close_window (int use_shrink_box);
  138. static void move_window (int x,int y);
  139. static int rect_intersect (GRECT *rec1,GRECT *rec2);
  140. static void redraw_window (int all);
  141. static int handle_message (int pipe[8]);
  142. static void event_loop (void);
  143.  
  144. #endif
  145.  
  146.  
  147. /* Calculate position of a pupil
  148.  
  149.    Input:
  150.      int mdx,mdy : direction to position of mouse
  151.                    from center of eye
  152.    Output:
  153.      int *dx,*dy : direction of pupil from center of eye
  154.  
  155.    The position of the pupil is within an 9 x 11 rectangle
  156.    around the center of the eye.
  157. */
  158.  
  159. static void position (mdx,mdy,dx,dy)
  160. int mdx,mdy,*dx,*dy;
  161.  
  162. {int adx,ady,m;
  163.                  /* Evaluate maximum absolute value of mdx and mdy */
  164.  adx = (mdx < 0) ? (-mdx) : mdx;
  165.  ady = (mdy < 0) ? (-mdy) : mdy;
  166.  m = max (adx,ady);
  167.  
  168.  if (m)   /* Not zero ? Evaluate point within 9 x 11 rectangle */
  169.   {
  170.    mdx *= 4;  mdy *= 5;
  171.    *dx = mdx / m;  *dy = mdy / m;
  172.   }
  173.   else    /* Mouse is on center of eye */
  174.    *dx = *dy = 0;
  175. }
  176.  
  177.  
  178. /* Calculate position of pupils from mouse position
  179.  
  180.    Input:
  181.      int mousex,mousey : position of mouse
  182.  
  183.    The position of the pupils is stored in variable new_eye.
  184.    The function returns TRUE if the position of the pupils has
  185.    changed, otherwise FALSE is returned.
  186. */
  187.  
  188. static int new_position (mousex,mousey)
  189. int mousex,mousey;
  190.  
  191. {int work_x_center,work_y_center;
  192.  int mouse_dx,mouse_dy;
  193.  int left_dy,right_dy;
  194.                                   /* center of work area */
  195.  work_x_center = work_x_origin + (WORK_WIDTH >> 1);
  196.  work_y_center = work_y_origin + (WORK_HEIGHT >> 1);
  197.                                   /* direction to mouse position */
  198.  mouse_dx = mousex - work_x_center;
  199.  mouse_dy = mousey - work_y_center;
  200.                                  /* Position of pupil of left eye */
  201.  position (mouse_dx+EYE_DX,mouse_dy+EYE_DY,
  202.            &(new_eye.left_dx),&left_dy);
  203.                                  /* Position of pupil of right eye */
  204.  position (mouse_dx-EYE_DY,mouse_dy+EYE_DY,
  205.            &(new_eye.right_dx),&right_dy);
  206.                          /* Pupils should have the same y-position */
  207.  new_eye.dy = (left_dy + right_dy) >> 1;
  208.                          /* Check if position has changed */
  209.  return (   new_eye.left_dx != last_eye.left_dx
  210.          || new_eye.right_dx != last_eye.right_dx
  211.          || new_eye.dy != last_eye.dy);
  212. }
  213.  
  214.  
  215. /* Save current position of pupils
  216. */
  217.  
  218. static void save_position ()
  219.  
  220. {last_eye.left_dx  = new_eye.left_dx;
  221.  last_eye.right_dx = new_eye.right_dx;
  222.  last_eye.dy       = new_eye.dy;
  223. }
  224.  
  225.  
  226. /* Draw pupils at given position
  227.  
  228.    Input:
  229.      EYE_DATA *eye : structure with position of pupils
  230. */
  231.  
  232. static void eyes (eye)
  233. EYE_DATA *eye;
  234.  
  235. {register int work_x_center,work_y_center;
  236.  int xy[4];
  237.  int left_eye_x,left_eye_y;
  238.  int right_eye_x,right_eye_y;
  239.                                  /* center of work area */
  240.  work_x_center = work_x_origin + (WORK_WIDTH >> 1);
  241.  work_y_center = work_y_origin + (WORK_HEIGHT >> 1);
  242.  
  243.  left_eye_x  = work_x_center - EYE_DX; /* center of eyes */
  244.  right_eye_x = work_x_center + EYE_DX;
  245.  left_eye_y  = right_eye_y = work_y_center - EYE_DY;
  246.  
  247.  xy[0] = left_eye_x + eye->left_dx - 1; /* rectangle representing */
  248.  xy[1] = left_eye_y + eye->dy - 2;      /* pupil of left eye */
  249.  xy[2] = left_eye_x + eye->left_dx + 1;
  250.  xy[3] = left_eye_y + eye->dy + 2;
  251.  vr_recfl (handle,xy);
  252.  
  253.  xy[0] = right_eye_x + eye->right_dx - 1; /* dito right eye */
  254.  xy[1] = right_eye_y + eye->dy - 2;
  255.  xy[2] = right_eye_x + eye->right_dx + 1;
  256.  xy[3] = right_eye_y + eye->dy + 2;
  257.  vr_recfl (handle,xy);
  258. }
  259.  
  260.  
  261. /* Draw background of window
  262.    Fill the window, draw eye-ellipses
  263. */
  264.  
  265. static void face ()
  266.  
  267. {int rect[4];
  268.  int xc,yc;
  269.  
  270.  rect[0] = work_x_origin;       /* Work area rectangle */
  271.  rect[1] = work_y_origin;
  272.  rect[2] = work_x_origin + WORK_WIDTH;
  273.  rect[3] = work_y_origin + WORK_HEIGHT;
  274.  
  275.                                /* Center of work area */ 
  276.  xc = work_x_origin + (WORK_WIDTH >> 1);
  277.  yc = work_y_origin + (WORK_HEIGHT >> 1);
  278.  
  279.  vsf_color (handle,0);      /* white fill */
  280.  vswr_mode (handle,1);      /* replace mode */
  281.  vr_recfl (handle,rect);    /* fill background */
  282.  vsf_color (handle,1);      /* restore black fill */
  283.  vsf_interior (handle,0);   /* hollow fill */
  284.                             /* draw left eye */
  285.  v_ellipse (handle,xc-EYE_DX,yc-EYE_DY,8,11);
  286.                             /* draw right eye */
  287.  v_ellipse (handle,xc+EYE_DX,yc-EYE_DY,8,11);
  288.  vsf_interior (handle,1);   /* restore solid fill */
  289.  vswr_mode (handle,3);      /* restore XOR mode */
  290. }
  291.  
  292.  
  293. /* Open the window
  294.  
  295.    Input:
  296.      int use_grow_box : TRUE if a growing box has to be drawn
  297.                         on opening. 
  298. */
  299.  
  300. static void open_window (use_grow_box)
  301. int use_grow_box;
  302.  
  303. {int win_x,win_y,win_width,win_height;
  304.  
  305.  if (whandle <= 0)    /* Window closed ? */
  306.   {
  307.                       /* Calculate size of window */
  308.                       /* from size of work area */
  309.    if (wind_calc (WC_BORDER,win_components,
  310.                   work_x_origin,work_y_origin,
  311.                   WORK_WIDTH,WORK_HEIGHT,
  312.                   &win_x,&win_y,&win_width,&win_height) == 0)
  313.      return;     /* Error ? finished */
  314.                                          /* Create window */
  315.    whandle = wind_create (win_components,0,0,win_width,win_height);
  316.    if (whandle <= 0) return;             /* Error ? finished */
  317.  
  318.    if (use_grow_box)                     /* Growing box */
  319.      graf_growbox (work_x_origin + WORK_WIDTH/2,
  320.                    work_y_origin + WORK_HEIGHT/2,1,1,
  321.                    work_x_origin,work_y_origin,
  322.                    WORK_WIDTH,WORK_HEIGHT);
  323.  
  324.    if (win_components & NAME)   /* Set name if requested */
  325.      wind_set(whandle,WF_NAME,"eyes",0,0);
  326.                                          /* Open the window */
  327.    wind_open (whandle,win_x,win_y,win_width,win_height);
  328.   }
  329.   else                /* Window already open */
  330.    wind_set (whandle,WF_TOP,0,0,0,0);   /* Set window to top */
  331.  
  332.                       /* Set default attributes */
  333.  vsf_interior (handle,1);   /* Solid fill */
  334.  vsf_color (handle,1);      /* Fill with colour 1 */
  335.  vswr_mode (handle,3);      /* XOR mode */
  336.  vsf_perimeter (handle,1);  /* Perimeter visible */
  337. }
  338.  
  339.  
  340. /* Open the window and restore top window
  341.  
  342.    Input:
  343.      int use_grow_box : TRUE if a growing box has to be drawn
  344.                         on opening. 
  345. */
  346.  
  347. static void open_back_window (use_grow_box)
  348. int use_grow_box;
  349.  
  350. {int top_window,dummy;
  351.  
  352.  wind_update (BEG_UPDATE);  /* Start updating window */
  353.                             /* What is the current top window ? */
  354.  if (wind_get (0,WF_TOP,&top_window,&dummy,&dummy,&dummy) == 0)
  355.    top_window = -1;
  356.  
  357.  open_window (use_grow_box); /* Try to open the window */
  358.                              /* Window open ? restore top window */
  359.  if (whandle > 0 && top_window > 0)
  360.    wind_set (top_window,WF_TOP,0,0,0,0);
  361.  
  362.  wind_update (END_UPDATE);
  363. }
  364.  
  365.  
  366. /* Close the window
  367.  
  368.    Input:
  369.      int use_shrink_box : TRUE if a shrinking box has to be drawn
  370.                           on closing. 
  371. */
  372.  
  373. static void close_window (use_shrink_box)
  374. int use_shrink_box;
  375.  
  376. {
  377.  if (use_shrink_box)          /* Draw shrinking box */
  378.    graf_shrinkbox (work_x_origin + WORK_WIDTH/2,
  379.                    work_y_origin + WORK_HEIGHT/2,1,1,
  380.                    work_x_origin,work_y_origin,
  381.                    WORK_WIDTH,WORK_HEIGHT);
  382.  wind_close (whandle);        /* Close window */
  383.  wind_delete (whandle);       /* Clear handle */
  384.  whandle = 0;                 /* Window closed */
  385. }
  386.  
  387.  
  388. /* Move whandle window, recalculate origin of work area
  389.  
  390.    Input:
  391.      int x,y : new position of window
  392. */
  393.  
  394. static void move_window (x,y)
  395. int x,y;
  396.  
  397. {int win_x,win_y,win_width,win_height,dummy;
  398.  
  399.  wind_update (BEG_UPDATE);
  400.                    /* Calculate current position of window */
  401.  wind_get (whandle,WF_CURRXYWH,&win_x,&win_y,&win_width,&win_height);
  402.                    /* Set new position of window */
  403.  wind_set (whandle,WF_CURRXYWH,x,y,win_width,win_height);
  404.                    /* Recalculate position of work area */
  405.  wind_get (whandle,WF_WORKXYWH,&work_x_origin,&work_y_origin,
  406.            &dummy,&dummy);
  407.  wind_update (END_UPDATE);
  408. }
  409.  
  410.  
  411. /* Test intersection of two rectangles
  412.  
  413.    Input:
  414.      GRECT *rec1,*rec2 : pointer to structure of rectangles
  415.  
  416.    If the rectangles dont intersect, 0 is returned.
  417.    If they intersect, *rec2 is the intersection of the rectangles
  418.    and a value != 0 is returned.
  419. */
  420.  
  421. static int rect_intersect (rec1,rec2)
  422. register GRECT *rec1,*rec2;
  423.  
  424. {register int x,y,wi,hi;
  425.  
  426.  x = max (rec2->g_x,rec1->g_x);
  427.  y = max (rec2->g_y,rec1->g_y);
  428.  wi = min (rec2->g_x + rec2->g_w,rec1->g_x + rec1->g_w);
  429.  hi = min (rec2->g_y + rec2->g_h,rec1->g_y + rec1->g_h);
  430.  
  431.  rec2->g_x = x;
  432.  rec2->g_y = y;
  433.  rec2->g_w = wi - x;
  434.  rec2->g_h = hi - y;
  435.  
  436.  return (((wi > x) && (hi > y)));
  437. }
  438.  
  439.  
  440. /* Redraw window
  441.  
  442.    Input:
  443.      int all : TRUE if face and eyes have to be redrawn.
  444.                FALSE if only eyes have to be redrawn.
  445. */
  446.  
  447. static void redraw_window (all)
  448. int all;
  449.  
  450. {GRECT box,work;
  451.  int covered,clip[4];
  452.  int x,y,dummy;
  453.  int win_x,win_y,win_width,win_height;
  454.  static unsigned int covered_count = 0;
  455.  
  456.  if (whandle <= 0) return;  /* No window open ? finished */
  457.  
  458.  wind_update (BEG_UPDATE);
  459.                             /* Get position and size of work area */
  460.  wind_get (whandle,WF_WORKXYWH,&work.g_x,&work.g_y,
  461.                                &work.g_w,&work.g_h);
  462.                       /* Get position and size of first rectangle */
  463.  wind_get (whandle,WF_FIRSTXYWH,&box.g_x,&box.g_y,
  464.                                 &box.g_w,&box.g_h );
  465.                       /* Window may be totally covered */
  466.  if (box.g_w <= 0 && box.g_h <= 0)
  467.    covered_count++;
  468.   else
  469.    covered_count = 0;
  470.  
  471.  if (covered_count > 2) /* If more than 2 times totally covered */
  472.   {                     /* try to find a free area to move to */
  473.    x = desk_work[0] + RAND() % (desk_size[0] - (WORK_WIDTH >> 1));
  474.    y = desk_work[1] + RAND() % (desk_size[1]- (WORK_HEIGHT >> 1));
  475.                         /* Test height of eyes */
  476.    covered = wind_find (x + (WORK_WIDTH >> 1),
  477.                         y + (WORK_HEIGHT >> 1) - EYE_DY);
  478.  
  479.    if (covered == 0)  /* This location not covered ? */
  480.     {                 /* Calculate size of window */
  481.                       /* from size of work area */
  482.      wind_calc (WC_BORDER,win_components,x,y,WORK_WIDTH,WORK_HEIGHT,
  483.                 &win_x,&win_y,&win_width,&win_height);
  484.                       /* Set window to new position */
  485.      wind_set (whandle,WF_CURRXYWH,win_x,win_y,win_width,win_height);
  486.                       /* Recalculate work area */
  487.      wind_get (whandle,WF_WORKXYWH,&work_x_origin,&work_y_origin,
  488.                &dummy,&dummy);
  489.      covered_count = 0;          /* No longer covered */
  490.      goto end_redraw;
  491.     }
  492.   }
  493.             /* Window may be partly off screen */
  494.             /* Recalculate width and height */
  495.  work.g_w = min (work.g_w,desk_work[2]-work.g_x+1);
  496.  work.g_h = min (work.g_h,desk_work[3]-work.g_y+1);
  497.  
  498.  graf_mouse (M_OFF,(MFORM *)0);     /* Switch mouse off */
  499.  
  500.  while (box.g_w > 0 && box.g_h > 0) /* For all rectangles in list */
  501.   {
  502.    if (rect_intersect (&work,&box)) /* If intersection not empty */
  503.     {
  504.      clip[0] = box.g_x;             /* Calculate clip rectangle */
  505.      clip[1] = box.g_y;
  506.      clip[2] = box.g_x + box.g_w - 1;
  507.      clip[3] = box.g_y + box.g_h - 1;
  508.  
  509.      vs_clip (handle,1,clip);       /* Set clip rectangle */
  510.  
  511.      if (all)     /* Redraw everything ? Draw background */
  512.        face ();
  513.                            /* If last position valid and not */
  514.                            /* all to redraw: clear old position */
  515.      if (!all && last_eye.left_dx != NOT_VALID)
  516.        eyes (&last_eye);
  517.  
  518.      eyes (&new_eye);    /* Draw new position */
  519.     }
  520.                          /* Get nect rectangle from list */
  521.    wind_get (whandle,WF_NEXTXYWH,&box.g_x,&box.g_y,&box.g_w,&box.g_h);
  522.   }
  523.  graf_mouse (M_ON,(MFORM *)0);  /* Switch mouse on */
  524.  vs_clip (handle,1,desk_work); /* Reset to maximum clip rectangle */
  525.  save_position ();             /* Save position of eyes */
  526.  
  527. end_redraw:
  528.  
  529.  wind_update (END_UPDATE);
  530. }
  531.  
  532.  
  533. /* Handle message event
  534.  
  535.    Input:
  536.      int pipe[8] :  pointer to message buffer
  537.  
  538.    Value returned : TRUE if window was closed and program is
  539.       not an accessory. Then the program has to be terminated.
  540.       Otherwise FALSE is returned.
  541. */
  542.  
  543. static int handle_message (pipe)
  544. int pipe[8];
  545.  
  546. {register int this_is_open;
  547.  int return_val = FALSE;
  548.  
  549.  /* check if window open and message is for this window */
  550.  this_is_open = ((whandle >= 0) && (pipe[3] == whandle));
  551.  
  552.  
  553.  switch (pipe[0])
  554.   {
  555.    case WM_REDRAW: /* Redraw window */
  556.  
  557.           if (this_is_open)  /* Calculate new eye positions */
  558.            {                 /* from mouse position */
  559.             new_position (mouse_x,mouse_y);
  560.             redraw_window (TRUE);  /* Complete redraw */
  561.             last_x = mouse_x;      /* Save mouse position */
  562.             last_y = mouse_y;
  563.            }
  564.           break;
  565.  
  566.    case WM_TOPPED: /* Set window to top */
  567.    case WM_NEWTOP:
  568.  
  569.           if (this_is_open)
  570.            {
  571.             wind_update (BEG_UPDATE);
  572.             wind_set (whandle,WF_TOP,0,0,0,0);
  573.             wind_update (END_UPDATE);
  574.            }
  575.           break;
  576.  
  577.    case WM_CLOSED: /* Window closed (CLOSER activated) */
  578.  
  579.           if (this_is_open)
  580.            {
  581.             wind_update (BEG_UPDATE);
  582.             close_window (TRUE);
  583.             wind_update (END_UPDATE);
  584.             auto_open = FALSE;    /* Suppress automatic open */
  585.             if (_app)             /* For program set exit flag */
  586.               return_val = TRUE;
  587.            }
  588.           break;
  589.  
  590.    case WM_MOVED: /* Move window (MOVER activated) */
  591.  
  592.           if (this_is_open)
  593.             move_window (pipe[4],pipe[5]); /* Move to new position */
  594.           break;
  595.  
  596.    case AC_OPEN: /* Accessory opened */
  597.  
  598.           if (pipe[4] == menu_id)
  599.            {
  600.             wind_update (BEG_UPDATE);
  601.             open_window (TRUE);       /* Open foreground window */
  602.             wind_update (END_UPDATE);
  603.             auto_open = TRUE;         /* Activate automatic open */
  604.            }
  605.           break;
  606.  
  607.    case AC_CLOSE: /* Close accessory */
  608.  
  609.           if (pipe[3] == menu_id)
  610.             whandle = 0;  /* Just clear handle, nothing else */
  611.           break;
  612.   }
  613.  return (return_val);
  614. }
  615.  
  616.  
  617. /* Wait for events
  618. */
  619.  
  620. static void event_loop ()
  621.  
  622. {register int ev_mflags,event;
  623.  int kstate,key,clicks;
  624.  int state,quit;
  625.  int pipe[8];
  626.  int win_x,win_y,win_width,win_height;
  627.  static int wait_open = 0;
  628.  
  629.  quit = FALSE;
  630.  
  631.  do
  632.   {
  633.    ev_mflags = MU_MESAG;  /* In all cases wait for message */
  634.      
  635.                     /* Window closed and automatic open ? */
  636.    if ((whandle <= 0)  && auto_open)
  637.     {
  638.            /* Try to open background window after some time */
  639.      if (++wait_open > 12) open_back_window (TRUE);
  640.  
  641.      if (whandle <= 0)        /* Window not opened ? */
  642.        ev_mflags |= MU_TIMER; /* Additionally wait for timer */
  643.       else
  644.        wait_open = 0;         /* Clear wait count */
  645.     }
  646.  
  647.    /* Window open ? Wait for button to move window and
  648.       for timer to update position of eyes
  649.    */
  650.  
  651.    if (whandle > 0) ev_mflags |= (MU_BUTTON | MU_TIMER);
  652.                                     /* Now wait for event */
  653.    event = evnt_multi (ev_mflags,
  654.              2,0x1,1,               /* Mouse button event */
  655.              
  656.              0,0,0,0,0,             /* Mouse event 1 (not used) */
  657.              0,0,0,0,0,             /* Mouse event 2 (not used) */
  658.              pipe,                  /* Message event */
  659.              150,0,                 /* Timer event */
  660.              &mouse_x,&mouse_y,&state,&kstate,&key,&clicks);
  661.  
  662. #ifdef SHOW_ACTIVITY
  663.  
  664. /* Invert a 2x2 pixel rectangle in the upper left corner
  665.    of the screen on every occurance of an event
  666. */
  667.  
  668. {int attrib[5];
  669.  static int area[4] = { 0,0,2,2 };
  670.  
  671.  
  672.  wind_update (BEG_UPDATE);
  673.  vqf_attributes(handle,attrib);    /* Inquire attributes */
  674.  vs_clip (handle,1,area);          /* Set clip reactangle */
  675.  vswr_mode (handle,3);             /* Set XOR mode */
  676.  vsf_color (handle,1);             /* Fill color 1 */
  677.  vr_recfl (handle,area);           /* Fill rectangle */
  678.  vswr_mode (handle,attrib[3]);     /* Restore write mode */
  679.  vsf_color (handle,1);             /* Restore fill colour */
  680.  wind_update (END_UPDATE);
  681. }
  682. #endif
  683.                    /* Shortcut if nothing happened */
  684.    if (   (event == MU_TIMER)
  685.        && (mouse_x == last_x) && (mouse_y == last_y))
  686.      continue;
  687.                                /* Handle messages */
  688.    if (event & MU_MESAG) quit = handle_message (pipe);
  689.  
  690.                    /* No window open ? no more actions */
  691.    if (whandle <= 0) continue;
  692.  
  693.                    /* Handle double-clicks (close window) */
  694.    if ((event & MU_BUTTON) && state==1 && clicks==2)
  695.     {
  696.      wind_update (BEG_UPDATE);
  697.      close_window (TRUE);
  698.      wind_update (END_UPDATE);
  699.      auto_open = FALSE;         /* Suppress automatic open */
  700.      if (_app) quit = TRUE;     /* Quit for program */
  701.      continue;
  702.     }
  703.                  /* Handle single button down (move window) */
  704.    if ((event & MU_BUTTON) && state == 1 && clicks==1)
  705.     {
  706.      wind_get (whandle,WF_CURRXYWH,&win_x,&win_y,
  707.                &win_width,&win_height);
  708.      graf_dragbox (win_width,win_height,win_x,win_y,
  709.                    desk_work[0],desk_work[1],
  710.                    desk_size[0]+WORK_WIDTH,desk_size[1]+WORK_HEIGHT,
  711.                    &win_x,&win_y);
  712.      move_window (win_x,win_y);
  713.     }
  714.                                /* Handle timer */
  715.    if (   (event & MU_TIMER)   /* Mouse and eye position changed ? */
  716.        && (mouse_x != last_x || mouse_y != last_y)
  717.        && (new_position (mouse_x,mouse_y)))
  718.     {
  719.      redraw_window (FALSE);        /* Redraw eyes */
  720.      last_x = mouse_x;             /* Save last mouse position */
  721.      last_y = mouse_y;
  722.     }
  723.   }
  724.  while (!quit);
  725. }
  726.  
  727.  
  728. /* Main program
  729. */
  730.  
  731. int main ()
  732.  
  733. {register int i;
  734.  int dummy;
  735.  int work_in[11];
  736.  int work_out[57];
  737.  
  738.  appl_id = appl_init ();       /* Initialize application */
  739.  
  740.  if (appl_id >= 0)
  741.   {
  742.    for (i = 0; i < 10; i++)    /* Initialize attributes */
  743.      work_in[i] = 1;
  744.    work_in[10] = 2;            /* Use raster coordinates */
  745.  
  746.    handle = graf_handle (&dummy,&dummy,&dummy,&dummy);
  747.  
  748.    v_opnvwk (work_in,&handle,work_out);
  749.    if (handle != 0)
  750.     {
  751.               /* Get desktop work-area as maximum clip rectangle */
  752.      wind_get (0,WF_WORKXYWH,&(desk_work[0]),&(desk_work[1]),
  753.                &(desk_size[0]),&(desk_size[1]));
  754.      desk_work[2] = desk_work[0] + desk_size[0];
  755.      desk_work[3] = desk_work[1] + desk_size[1];
  756.  
  757.      work_x_origin += desk_work[0]; /* Position own window within */
  758.      work_y_origin += desk_work[1]; /* desktop work area */
  759.  
  760.      if (!_app)            /* Accessory ? register menu entry */
  761.        menu_id = menu_register (appl_id,MENU_ENTRY);
  762.  
  763.      graf_mouse (0,(MFORM *)0); /* Set mouse cursor to arrow */
  764.  
  765.      event_loop ();             /* Event loop */
  766.  
  767.      v_clsvwk (handle);
  768.     }
  769.    appl_exit ();
  770.   }
  771.  return (0);
  772. }
  773.